﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ProcessBase.Models;
using SubstrateHelper.Data;

namespace SubstrateHelper.Helpers
{
    public class ProcessTraceHelper
    {
        public static List<ProcessStatistics> GetTracingLinks(string guid)
        {
            List<ProcessStatistics> links;
            using (var scope = Global.Host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var Db = services.GetRequiredService<SubstrateHelperDbContext>();
                    //
                    var start = Db.ProcessStatistics.Where(x => x.Guid == guid).FirstOrDefault();
                    if (start == null)
                    {
                        return null;
                    }
                    //
                    links = new List<ProcessStatistics>();
                    _TraceBackward(start, links, Db);
                    _TraceForeward(start, links, Db);

                    links = links.Distinct().OrderBy(x => x.ProcessName).ToList();


                    

                }
                catch (Exception ex)
                {
                    links = null;
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "MakeStatistics");
                    
                }
            }

            return links;
        }

        public static List<ProcessStatistics> GetTracingLinksBackwardOnly(string guid)
        {
            List<ProcessStatistics> links;
            using (var scope = Global.Host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var Db = services.GetRequiredService<SubstrateHelperDbContext>();
                    //
                    var start = Db.ProcessStatistics.Where(x => x.Guid == guid).FirstOrDefault();
                    if (start == null)
                    {
                        return null;
                    }
                    //
                    links = new List<ProcessStatistics>();
                    _TraceBackward(start, links, Db);                    

                    links = links.Distinct().OrderBy(x => x.ProcessName).ToList();
                }
                catch (Exception ex)
                {
                    links = null;
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "MakeStatistics");

                }
            }

            return links;
        }


        static void _TraceBackward(ProcessStatistics current,List<ProcessStatistics>links,SubstrateHelperDbContext Db)
        {
            //递归退出条件
            if (current==null)
            {
                return;
            }

            //加入当前guid
            links.Add(current);

            //往过去追溯
            //来料标识
            var inputLotString =current.LotNoInput;
            string[] inputLots = inputLotString.Split(new char[] { ';', '；', ',', '，' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (var lot in inputLots)
            {
                try
                {
                    var backwardItem= Db.ProcessStatistics.Where(x =>x.MainLotNo==current.MainLotNo&&x.ProcessName!=current.ProcessName && x.LotNoOutput == lot).FirstOrDefault();
                    _TraceBackward(backwardItem, links, Db);
                    
                }
                catch
                {

                }

            }
        }

        static void _TraceForeward(ProcessStatistics current, List<ProcessStatistics> links, SubstrateHelperDbContext Db)
        {
            //递归退出条件
            if (current==null)
            {
                return;
            }

            //加入当前guid
            links.Add(current);

            //往未来追溯
            //产出标识
            var outputLot = current.LotNoOutput;


            try
            {
                var query = Db.ProcessStatistics.Where(x =>x.MainLotNo==current.MainLotNo && x.ProcessName != current.ProcessName && x.LotNoInput.Contains(outputLot));
                foreach (var g in query)
                {
                    _TraceForeward(g, links,Db);
                }
            }
            catch
            {

            }
        }
    }
}
